/*
*	Copyright (C) 2014  Julio Montes, Mario Carrillo
*	
*	Julio Montes e-mail: imc.coder@gmail.com 
*
*	Mario Carrillo e-mail: mario_90ago@live.com.mx
*
*	BSD 3-Clause License
*/

#ifndef SDK_UTIL_H
#define SDK_UTIL_H

#include <wx/wx.h>

#ifdef SDK_DEBUG
    #define LOGD( MSG ) sdk::debugMessage( __BASE_FILE__, __FUNCTION__, __LINE__, MSG );
    #define LOGC( MSG ) sdk::debugMessageConsole( __BASE_FILE__, __FUNCTION__, __LINE__, MSG )
#else
    #define LOGD( MSG )
    #define LOGC( MSG )
#endif

namespace sdk
{
    bool stringToBool( const wxString &str );

    wxColour stringToColor( const wxString &colorString );

    /**
    * @brief funcion para mostrar un dialogo de error.
    *
    * @param title titulo de la ventana
    * @param error descripcion del error
    * @param details detalles del error
    * @param help mensage para ayudar al usuario a resolver el error
    */
    void errorDialog( const wxString &title, const wxString &error, const wxString &details, const wxString &help );

    /**
    *
    */
    void debugMessage( const char *file, const char *func, int line, const wxString &msg );

    /**
    *
    */
    void debugMessageConsole( const char *file, const char *func, int line, const wxString &msg );


    /**
    * @brief funcion para crear un directorio.
    *
    * Si el directorio ya existe no hace nada, en caso de algun error muestra un dialogo de error
    *
    * @param dir directorio a crear
    * @return verdadero si el directorio ya existe o lo creo con exito, falso en caso de ocurrir algun error
    * al crear el directorio
    */
    bool mkDir( const wxString &dir );

    /**
    * @brief funcion para crear un un archivo.
    *
    * Si el archivo ya existe lo sobreescribe, si el directorio no existe lo crea para despues crear el archivo
    *
    * @param file ruta del archivo a crear o sobreescribir.
    * @return verdadero si se creo o sobreescribio el archivo con exito, falso en caso contrario.
    */
    bool mkFile( const wxString &file );

    /**
    * @brief funcion para obtener un nuevo identificador.
    *
    * este metodo es util cuando se quiere obtener un nuevo identificador o recuperar uno que ya existe
    * el primer identificador que regresa esta funcion es el 1, despues el 2 y asi sucesivamente.
    *
    * @param key nombre del identificador, se recomienda que sea unico para obtener un identificador unico.
    * @return un identificador, ya sea uno nuevo o uno que ya existe, todo depende del parametro.
    */
    size_t getId( const wxString &key );


    /**
    *
    */
    template <class RandomAccessIterator, class T, class Compare, class Match>
    RandomAccessIterator binarySearch( RandomAccessIterator first, RandomAccessIterator last, T value, Compare compare, Match match )
    {
        RandomAccessIterator half = first + (( last - first ) / 2 );

        while( first < last )
        {
            if( match( *half, value ) )
            {
                return half;
            }
            else
            {
                if( compare( *half, value ) )
                    first = half + 1;
                else
                    last = half - 1;
            }

            half = first + (( last - first ) / 2 );
        }

        return last;
    }


    /**
    *
    */
    template <class RandomAccessIterator, class T, class Compare, class Match>
    std::pair<RandomAccessIterator,RandomAccessIterator> equalRange( RandomAccessIterator first, RandomAccessIterator last, T value, Compare compare, Match match )
    {
        RandomAccessIterator found = sdk::binarySearch( first, last, value, compare, match );
        std::pair<RandomAccessIterator,RandomAccessIterator> result;
        result.first = last;
        result.second = last;

        if( found != last )
        {
            result.first = found;
            result.second = found;

            while( --result.first >= first && match( *result.first, value ) );
            ++result.first;

            while( ++result.second < last && match( *result.second, value ) );
        }

        return result;
    }
}

#endif // SDK_UTIL_H
